MOOC Utils

Utils like auto assignment solver extension and course notice announcment notification for MOOC courses

Subscription management

Introduction#

Per-user course subscriptions and optional notification channels. Create path, ownership checks, and how CourseService makes sure the course row exists first.

Project structure#

The subscription management spans a FastAPI backend and a Next.js frontend:

  • Backend (FastAPI):
  • API routers define endpoints for subscription operations.
  • Services encapsulate business logic for subscriptions and notification channels.
  • Models define persistence for subscriptions, courses, notification channels, and users.
  • Schemas define request/response data contracts.
  • Frontend (Next.js):
  • React components integrate with the backend via typed API helpers.
  • TanStack Query manages caching and optimistic updates for subscriptions.

Core components#

  • Subscription model: Tracks per-user subscriptions to courses with timestamps and activation flag.
  • Subscription service: Handles creation, listing, and deletion of subscriptions with deduplication semantics.
  • Course service: Manages course metadata and caches course records.
  • Notification channel model and service: Stores user notification channels (e.g., email, Telegram) and supports enabling/disabling.
  • User model and schemas: Identifies users and exposes profile-related fields.
  • API router for subscriptions: Exposes endpoints for creating, listing, and deleting subscriptions.
  • Frontend integration: React components and API client for subscription management.

Architecture overview#

The subscription workflow integrates frontend requests with backend services and persistence. Authentication is enforced for subscription operations. Course lookup keeps subscriptions target valid courses. Subscriptions are scoped to users and persisted with uniqueness constraints.

Detailed component analysis#

Subscription model and service#

  • Model fields include foreign keys to User and Course, timestamps, and an activation flag. Uniqueness constraint prevents duplicate subscriptions per user-course pair.
  • Service methods:
  • Subscribe: Creates a subscription or returns an existing one on integrity errors.
  • List all and list for user: Ordered by creation time descending.
  • Delete: Removes a subscription.

Course lookup and validation#

  • CourseService searches and caches courses so a course row exists before subscription creation.
  • Uniqueness on course code prevents duplicates and supports efficient lookups.

Notification channel management#

  • NotificationChannel stores user-specific channels (e.g., email, Telegram) with uniqueness constraints across user, channel type, and address.
  • NotificationChannelService supports listing, creating (deduplicate on conflict), and disabling channels.

User preferences handling#

  • User model includes optional identifiers (e.g., Telegram ID) and activity flag.
  • User update schema allows partial updates to profile fields.
  • Domain models include Course and Announcement entities for higher-level abstractions.

API endpoints for subscription operations#

  • Create subscription
  • Method: POST
  • Path: /subscriptions
  • Authenticated: Yes
  • Request body: SubscriptionCreate (course_code)
  • Response: SubscriptionResponse
  • Behavior: Validates course existence; creates or retrieves subscription; returns created_at ordering
  • List subscriptions
  • Method: GET
  • Path: /subscriptions
  • Authenticated: Yes
  • Response: array of SubscriptionResponse
  • Behavior: Returns user-scoped subscriptions ordered by created_at descending
  • Delete subscription
  • Method: DELETE
  • Path: /subscriptions/{subscription_id}
  • Authenticated: Yes
  • Response: 204 No Content
  • Behavior: Validates ownership; deletes subscription

Request/Response schemas#

  • SubscriptionCreate
  • Fields: course_code (string)
  • SubscriptionResponse
  • Fields: id, user_id, course_id, is_active, created_at (datetime)
  • NotificationChannelCreate
  • Fields: channel (string), address (string), is_active (bool, default true)
  • NotificationChannelResponse
  • Fields: id, user_id, channel, address, is_active, created_at (datetime)
  • UserUpdate
  • Fields: email (optional), name (optional), telegram_id (optional), is_active (optional)
  • UserResponse
  • Fields: id, email, name, telegram_id, is_active, created_at, updated_at
  • CourseResponse
  • Fields: id, code, title, url, instructor, institute, nc_code, created_at, updated_at

Frontend integration patterns#

  • SubscriptionManager fetches subscriptions and courses, renders subscription cards, and supports unsubscription via mutation.
  • API client functions encapsulate HTTP calls for subscriptions and other resources.
  • TanStack Query invalidates queries after mutations to keep UI in sync.

Dependency analysis#

  • API router depends on authentication, subscription service, and course service.
  • Subscription service depends on subscription and course models.
  • Course service depends on external Swayam service and course model.
  • Notification channel service depends on notification channel model.
  • Frontend components depend on API client and TanStack Query.

Performance considerations#

  • Deduplication on subscription creation avoids redundant writes and uses database constraints.
  • Ordering by created_at descending reduces UI sorting overhead.
  • Course caching minimizes repeated external lookups and improves responsiveness.
  • Frontend caching via TanStack Query reduces network calls and accelerates list operations.

Troubleshooting guide#

  • Course not found during subscription creation:
  • Verify course_code correctness and that the course exists in the cache.
  • Check CourseService.get_by_code behavior and external course provider availability.
  • Access denied on unsubscribe:
  • Ensure the subscription belongs to the current user; otherwise, a 403 is raised.
  • Duplicate subscription:
  • Creation returns the existing subscription due to uniqueness constraints; no error is raised.
  • Empty subscription list:
  • Confirm user has active subscriptions and that the list endpoint is called with proper authentication.

Conclusion#

Create only after the course exists. Ownership checks belong in the service, not the React form.

Appendices#

API endpoint reference#

  • POST /subscriptions
  • Authenticated: Yes
  • Request: SubscriptionCreate
  • Response: SubscriptionResponse
  • Notes: Creates or retrieves subscription for the given course_code
  • GET /subscriptions
  • Authenticated: Yes
  • Response: array of SubscriptionResponse
  • Notes: Lists user’s subscriptions ordered by created_at descending
  • DELETE /subscriptions/{subscription_id}
  • Authenticated: Yes
  • Response: 204 No Content
  • Notes: Requires ownership of the subscription

Example workflows#

  • Subscribe to a course:
  • Frontend calls createSubscription with course_code.
  • Backend validates course existence and persists subscription.
  • Frontend updates local cache and displays the new subscription.
  • Unsubscribe from a course:
  • Frontend triggers deleteSubscription.
  • Backend verifies ownership and deletes the subscription.
  • Frontend invalidates cache and removes the subscription card.